package com.lhkj.ct.framework.mybatis.handlers;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import com.lhkj.ct.base.annntation.DataPermission;
import com.lhkj.ct.base.enums.DataScope;
import com.lhkj.ct.base.utils.ShiroUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.Optional;

/**
 * 数据权限控制器
 *
 * @author zc
 * @since 2021-12-10 13:28
 */
@Slf4j
public class MyDataPermissionHandler implements MultiDataPermissionHandler {

    /**
     * 获取数据权限 SQL 片段。
     * 旧的 getSqlSegment(Expression, String) 方法第一个参数包含所有的 where 条件信息，tips 如果 return 了 null 会覆盖原有的 where 数据，
     * 新版的 getSqlSegment(Table, Expression, String) 方法不能覆盖原有的 where 数据，tips 如果 return 了 null 则表示不追加任何 where 条件
     * Params:
     * table – 所执行的数据库表信息，可以通过此参数获取表名和表别名 where – 原有的 where 条件信息 mappedStatementId – Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
     * Returns:
     * JSqlParser 条件表达式，返回的条件表达式会拼接在原有的表达式后面（不会覆盖原有的表达式）
     * @param table             所执行的数据库表信息，可以通过此参数获取表名和表别名
     * @param where             原有的 where 条件信息
     * @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
     * @return
     */
    @SneakyThrows
    @Override
    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
        Class<?> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringPool.DOT)));
        String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringPool.DOT) + 1);
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            DataPermission annotation = method.getAnnotation(DataPermission.class);
            if (ObjectUtils.isNotEmpty(annotation)
                    && (method.getName().equals(methodName) || (method.getName() + "_COUNT").equals(methodName))
            ) {
                // 超级管理员不受数据权限控制、平台用户也不进行拦截
                if (ShiroUtil.isRoot() || ShiroUtil.isGuest()) {
                    return null;
                }
                return dataScopeFilter(annotation.orgAlias(),
                        annotation.orgIdColumnName(),
                        annotation.deptAlias(),
                        annotation.deptIdColumnName(),
                        annotation.userAlias(),
                        annotation.userIdColumnName(),
                        where);
            }
        }
        return null;
    }

    /**
     * 构建过滤条件
     *
     * @param where 当前查询条件
     * @return 构建后查询条件
     *
     */
    @SneakyThrows
    public static Expression dataScopeFilter(String orgAlias, String orgIdColumnName, String deptAlias, String deptIdColumnName, String userAlias, String userIdColumnName, Expression where) {

        String orgColumnName = StringUtils.isNotBlank(orgAlias) ? (orgAlias + StringPool.DOT + orgIdColumnName) : orgIdColumnName;

        String deptColumnName = StringUtils.isNotBlank(deptAlias) ? (deptAlias + StringPool.DOT + deptIdColumnName) : deptIdColumnName;

        String userColumnName = StringUtils.isNotBlank(userAlias) ? (userAlias + StringPool.DOT + userIdColumnName) : userIdColumnName;

        // 获取当前用户的数据权限,如果没有则查询本机构
        DataScope dataScope = Optional.ofNullable(ShiroUtil.getDataScope()).orElse(DataScope.ORGAN);
        String orgId, deptId, userId;
        String appendSqlStr = null;
        switch (dataScope) {
            // 所有則不限制
            case ALL:
                return  null;
            // 本部门
            case DEPT:
                deptId = ShiroUtil.getAuthUserInfo().getDeptId();
                appendSqlStr = deptColumnName + StringPool.EQUALS + deptId;
                break;
            // 部门及子部门数据
            case DEPT_CHILD:
                deptId = ShiroUtil.getAuthUserInfo().getDeptId();
                appendSqlStr = deptColumnName + " IN ( SELECT id FROM tbl_department WHERE id = " + deptId + " OR FIND_IN_SET( " + deptId + " , tree_path ) )";
                break;
            // 本人
            case SELF:
                userId = ShiroUtil.getAuthUserInfo().getUserId();
                appendSqlStr = userColumnName + StringPool.EQUALS + userId;
                break;
            // 默认本机构
            default:
                orgId = ShiroUtil.getAuthUserInfo().getOrganId();
                appendSqlStr = orgColumnName + StringPool.EQUALS + orgId;
                break;
        }
        // 如果没有条件，则不限制
        if (StringUtils.isBlank(appendSqlStr)) {
            return null;
        }

        Expression appendExpression = CCJSqlParserUtil.parseCondExpression(appendSqlStr);

//        if (where == null) {
            return appendExpression;
//        }
//        return new AndExpression(where, appendExpression);
    }


}

